package com.springengine.blefun;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {
    final static HashMap<String, String> mCharacteristicsDescription;
    final static HashMap<String, String> mServiesDescription;

    static {
        mServiesDescription = new HashMap<String, String>();
        mServiesDescription.put("Serial", "0000dfb0-0000-1000-8000-00805f9b34fb");

        mCharacteristicsDescription = new HashMap<String, String>();
        mCharacteristicsDescription.put("Data", "0000dfb1-0000-1000-8000-00805f9b34fb");
        mCharacteristicsDescription.put("AT", "0000dfb2-0000-1000-8000-00805f9b34fb");
    }

    private Handler mMainThreadHandler;

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothGatt mBluetoothGatt;


    private HashMap<String, ScanResult> mScanResult;

    private BroadcastReceiver mBroadcastReceiver;
    private String mCurrentConnectDeviceAddress;

    private TextView mLogView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mScanResult = new HashMap<String, ScanResult>();
        mLogView = (TextView)findViewById(R.id.logView);
        mLogView.setMovementMethod(ScrollingMovementMethod.getInstance());

        mMainThreadHandler = new Handler();
        initBle();
        startSearchBleDevice();
    }
    private void appendLogToLogView(final String s) {
        mMainThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                mLogView.append(s);
            }
        });
    }
    private  void initBle() {
        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();


        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(this.mBroadcastReceiver, filter);


        if (mBluetoothAdapter.isEnabled()) {
            Log.d("BLUE", "蓝牙已开启");
        } else {
            Log.d("BLUE", "蓝牙未开启，正在启动蓝牙");
//            startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 0);
            mBluetoothAdapter.enable();
        }
    }
    private void startSearchBleDevice() {
        BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
        scanner.stopScan(mScanCallback);
        scanner.startScan(mScanCallback);
    }

    public void onConnectButtonClick(View v) {
        EditText text = (EditText)findViewById(R.id.deviceAddress);
        mCurrentConnectDeviceAddress = text.getText().toString();

        ScanResult r = mScanResult.get(mCurrentConnectDeviceAddress);
        if (r == null) {
            appendLogToLogView("设备不存在\n");
            return;
        }
        mBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
        mBluetoothGatt = r.getDevice().connectGatt(this,false, mGattCallback);

    }
    public void onWriteToSerialButtonClick(View v) {
        EditText wrotenStringTextView = (EditText)findViewById(R.id.writeString);
        String wrotenString = wrotenStringTextView.getText().toString();
        if (mBluetoothGatt == null) {
            return;
        }
        BluetoothGattService serialService = mBluetoothGatt.getService(UUID.fromString(mServiesDescription.get("Serial")));
        if (serialService != null) {
            BluetoothGattCharacteristic serialCharacteristic = serialService.getCharacteristic(UUID.fromString(mCharacteristicsDescription.get("Data")));
            serialCharacteristic.setValue(wrotenString);
            mBluetoothGatt.writeCharacteristic(serialCharacteristic);
        }
    }
    public void onDisconnectButtonClick(View e) {
        if (mBluetoothGatt == null) {
            return;
        }
        mBluetoothGatt.disconnect();
        mBluetoothGatt = null;
        ((TextView)findViewById(R.id.logView)).setText("");
        mBluetoothAdapter.getBluetoothLeScanner().startScan(mScanCallback);
    }
    private ScanCallback mScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);

            String deviceAddres  = result.getDevice().getAddress();
            int serviceCount = result.getScanRecord().getServiceUuids().size();
            Log.d("BLUE", "搜索到设备" + result.getDevice().getAddress() + ", Rssi:" + String.valueOf(result.getRssi()) + ", Name: "+ result.getDevice().getName() + "服务数: "+ String.valueOf(serviceCount) + "\n");
            mScanResult.put(deviceAddres, result);
            appendLogToLogView("搜索到设备" + result.getDevice().getAddress() + ", Rssi:" + String.valueOf(result.getRssi()) + ", Name: "+ result.getDevice().getName() + "服务数: "+ String.valueOf(serviceCount) + "\n");
        }
        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            // 批量回调，一般不推荐使用，使用上面那个会更灵活
        }
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            // 扫描失败，并且失败原因
            Log.d("BLUE", "扫描失败，错误代码:" + String.valueOf(errorCode));
        }
    };
    private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);

            if (status != BluetoothGatt.GATT_SUCCESS) { // 连接失败判断
                appendLogToLogView("连接失败\n");
                return;
            }
            if (newState == BluetoothProfile.STATE_CONNECTED) { // 连接成功判断
                appendLogToLogView("连接成功，正在发现服务\n");
                mBluetoothGatt.discoverServices(); // 发现服务
                return;
            }
            if (newState == BluetoothProfile.STATE_DISCONNECTED) {  // 连接断开判断
                appendLogToLogView("断开连接\n");
                return;
            }

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);

            for (BluetoothGattService service : gatt.getServices()) {
                appendLogToLogView("发现服务" + service.getUuid().toString() + "\n");
                    for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                        appendLogToLogView("|----特征:" + characteristic.getUuid().toString() + "\n");
                    }
            }

            BluetoothGattService serialService = gatt.getService(UUID.fromString(mServiesDescription.get("Serial")));
            if (serialService != null) {
                BluetoothGattCharacteristic serialCharacteristic = serialService.getCharacteristic(UUID.fromString(mCharacteristicsDescription.get("Data")));
                gatt.setCharacteristicNotification(serialCharacteristic, true);
            }

        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            Log.d("BLUE", "Read: " + characteristic.getValue().toString());
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            Log.d("BLUE", "Write: " + characteristic.getValue().toString());
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            appendLogToLogView("接受到数据：" + new String(characteristic.getValue(), StandardCharsets.US_ASCII) + "\n");
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
            super.onReliableWriteCompleted(gatt, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
        }
    };
}
